#include "../StdInc.h"
#include "FrozenHelper.h"
#include "SettleHelper.h"
#include "DBCommon.h"

namespace GSTrader
{
	namespace TradeService
	{
		CFrozenHelper::CFrozenHelper(CDataBase* pDataBase) : m_pDataBase(pDataBase)
		{
			m_pDBCommon = pDataBase->m_pDBCommon;
			m_pSettleHelper = pDataBase->m_pSettleHelper;
		}

		CFrozenHelper::~CFrozenHelper()
		{
		}

		bool CFrozenHelper::AddOrderFrozen(COrderFrozenTable* pOrder, TotalFrozenCursor& totalFrozenCursor)
		{
			if (pOrder == NULL || totalFrozenCursor.isEmpty())
				return false;

			OrderFrozenCursor orderFrozenCursor(dbCursorForUpdate);
			if (totalFrozenCursor->GetOrderFrozen(pOrder->m_nOrderId, orderFrozenCursor))
				return false;

			orderFrozenCursor.at(insert(*pOrder));

			totalFrozenCursor->m_dFrozenCommission += orderFrozenCursor->m_dFrozenCommission;
			totalFrozenCursor->m_dFrozenMargin  += orderFrozenCursor->m_dFrozenMargin;
			totalFrozenCursor->m_dFrozenPremium += orderFrozenCursor->m_dFrozenPremium;

			return true;
		}

		bool CFrozenHelper::OnRetOrder(AccountDataCursor& accountData, OrderCursor& orderCursor, CAccountInstrument* pAccountInstrument)
		{
			orderCursor->CalcForzen(m_pSettleHelper, pAccountInstrument);
			orderCursor.update();

			m_pSettleHelper->CalcFroZen(accountData, false);
			return true;
		}

		bool CFrozenHelper::OnRetTrade(AccountDataCursor& accountData, OrderCursor& orderCursor, TradeCursor& tradeCursor, CAccountInstrument* pAccountInstrument)
		{
			orderCursor->CalcForzen(m_pSettleHelper, pAccountInstrument);
			orderCursor.update();

	

			m_pSettleHelper->CalcFroZen(accountData, false);
			return true;
		}

		bool CFrozenHelper::OnRetOrder(COrderTable* pOrder, TotalFrozenCursor& tfCursor, CAccountInstrument* pAccountInstrument)
		{
			if (pOrder == NULL || pAccountInstrument == NULL)
				return false;

			pOrder->CalcForzen(m_pSettleHelper, pAccountInstrument);

			if (!m_pDBCommon->GetOrCreateTotalFrozenData(pOrder->m_nProviderId, tfCursor))
				return false;

			if (pOrder->IsCanceled()) 
			{
				DeleteOrderFrozen(pOrder->m_nID, tfCursor);
				return true;
			}

			COrderFrozenTable frozen(pOrder, m_pSettleHelper, pAccountInstrument);
			return AddOrderFrozen(&frozen, tfCursor);
		}

		bool CFrozenHelper::OnRetTrade(COrderTable* pOrder, CTradeTable* pTrade, TotalFrozenCursor& totalFrozenCursor, CAccountInstrument* pAccountInstrument)
		{
			if (pOrder == NULL || pTrade == NULL || pAccountInstrument == NULL)
				return false;

			pOrder->CalcForzen(m_pSettleHelper, pAccountInstrument);
			int nCalcType = pOrder->GetMarginCalcType();

			if (!m_pDBCommon->GetOrCreateTotalFrozenData(pTrade->m_nProviderId, totalFrozenCursor))
				return false;

			OrderFrozenCursor orderFrozenCursor(dbCursorForUpdate);
			if (!totalFrozenCursor->GetOrderFrozen(pOrder->m_nID, orderFrozenCursor))
				return false;


			bool bClose = pTrade->IsClose();

			double dCommission = m_pSettleHelper->CalcCommission(pTrade->m_nProviderId, pAccountInstrument, pTrade->m_dPrice, pTrade->m_nVolume, pTrade->m_nOpenClose);
			double dPremium = m_pSettleHelper->CalcPremium();
			double dMargin = m_pSettleHelper->CalcMargin(nCalcType, pTrade, pAccountInstrument);

			orderFrozenCursor->m_dFrozenCommission -= dCommission;
			totalFrozenCursor->m_dFrozenPremium += dCommission;

			if (bClose)
			{
				totalFrozenCursor->m_dUseMargin -= dMargin;
			}
			else
			{
				orderFrozenCursor->m_dFrozenMargin -= dMargin;
				totalFrozenCursor->m_dUseMargin += dMargin;
			}

			if (pOrder->m_nSide == osBuy)
			{
				totalFrozenCursor->m_dFrozenPremium += dPremium;
				orderFrozenCursor->m_dFrozenPremium += dPremium;
			}

			if (pOrder->m_LeavesQty <= 0)
			{
				orderFrozenCursor.remove();
			}
			return true;
		}

		bool CFrozenHelper::DeleteOrderFrozen(int nOrderId, TotalFrozenCursor& totalFrozenCursor)
		{
			if (totalFrozenCursor.isEmpty())
				return false;

			OrderFrozenCursor orderFrozenCursor(dbCursorForUpdate);
			if (!totalFrozenCursor->GetOrderFrozen(nOrderId, orderFrozenCursor))
				return false;

			totalFrozenCursor->m_dFrozenCommission -= orderFrozenCursor->m_dFrozenCommission;
			totalFrozenCursor->m_dFrozenMargin -= orderFrozenCursor->m_dFrozenMargin;
			totalFrozenCursor->m_dFrozenPremium -= orderFrozenCursor->m_dFrozenPremium;

			orderFrozenCursor.remove();
			return true;
		}

		CPrepareFrozenHelper::CPrepareFrozenHelper(CDataBase* pDataBase) : m_pDataBase(pDataBase)
		{
			m_pDBCommon = pDataBase->m_pDBCommon;
		}

		CPrepareFrozenHelper::~CPrepareFrozenHelper()
		{

		}

		bool CPrepareFrozenHelper::OnNewOrder(CInputOrderTable* pOrder, PrepareForzenCursor& pfCursor)
		{
			if (!pOrder->IsClose()) 
				return false;

			CPrepareForzen forzen(pOrder);

			pfCursor.at(insert(forzen));
			return true;
		}

		bool CPrepareFrozenHelper::DeleteOrderFrozen(int nOrderId)
		{
			dbQuery dbQry;
			dbQry = "m_nOrderId = ", nOrderId;

			PrepareForzenCursor pfCursor(dbCursorForUpdate);
			if (pfCursor.select(dbQry) > 0)
			{
				pfCursor.remove();
				return true;
			}

			return false;
		}

		bool CPrepareFrozenHelper::OnOrderError(int nOrderId)
		{
			return DeleteOrderFrozen(nOrderId);
		}

		bool CPrepareFrozenHelper::OnRetOrder(int nOrderId)
		{
			return DeleteOrderFrozen(nOrderId);
		}

		int CPrepareFrozenHelper::GetForzenQty(int nProviderId, int nInstrumentId, int nSide, int nHegdeFlag)
		{
			dbQuery dbQry;
			dbQry = "m_nProviderId =", nProviderId, " and m_nInstrumentId =", nInstrumentId;

			int nQty = 0;
			PrepareForzenCursor pfCursor(dbCursorForUpdate);
			if (pfCursor.select(dbQry) > 0)
			{
				do
				{
					if (nHegdeFlag == hfSpeculation)
					{
						if (nSide == osBuy)
						{
							nQty += pfCursor->m_nSpeculationBuyNumber;
						}
						else if (nSide == osSell)
						{
							nQty += pfCursor->m_nSpeculationSellNumber;
						}
					}
					else if (nHegdeFlag == hfArbitrage)
					{
						if (nSide == osBuy)
						{
							nQty += pfCursor->m_nArbitrageBuyNumber;
						}
						else if (nSide == osSell)
						{
							nQty += pfCursor->m_nArbitrageSellNumber;
						}
					}
					else if (nHegdeFlag == hfHedge)
					{
						if (nSide == osBuy)
						{
							nQty += pfCursor->m_nHedgeBuyNumber;
						}
						else if (nSide == osSell)
						{
							nQty += pfCursor->m_nHedgeSellNumber;
						}
					}
				}
				while (pfCursor.next());
			}

			return nQty;
		}

	}
}